#pragma once        
#include <iostream>    
#include <string>    
#include <queue>    
#include <unistd.h>    
#include <pthread.h> 
   
using namespace std;
    
   
    const int g_num = 5;    
    template <class T>    
    class ThreadPool    
    {    
    private:    
        int num_; //线程池的大小   
        queue<T> task_queue_; //任务队列，使用STL的queue实现   
        pthread_mutex_t mtx_; //互斥锁  
        pthread_cond_t cond_; //条件变量
    public:    
        void Lock() { pthread_mutex_lock(&mtx_);}  
        void Unlock() { pthread_mutex_unlock(&mtx_);}   
        bool IsEmpety() { return task_queue_.empty();} 
        void Wait() { pthread_cond_wait(&cond_, &mtx_);}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
        void WakeUp() { pthread_cond_signal(&cond_);}     
        ThreadPool(int num = g_num) :num_(num)    
        {    
            pthread_mutex_init(&mtx_, nullptr);    
            pthread_cond_init(&cond_, nullptr);    
        }    
        //注意：在类中要让线程执行类内成员方法是不可行的，必须让线程执行静态方法
        static void* Rountine(void* args)
        {    
            pthread_detach(pthread_self());
            ThreadPool<T>* tp = static_cast<ThreadPool<T>*>(args); 
            tp->Lock(); 
            while (tp->IsEmpety()) 
            {
                tp->Wait();    
            }    
            T t;    
            tp->PopTask(t);     
            tp->Unlock();   
            return nullptr;
        }    
        //线程池初始化
        void InitThreadPool()    
        {    
            pthread_t tid;    
            for(int i = 0; i < num_; i++)    
            {    
                pthread_create(&tid, nullptr, Rountine, (void*)this);    
            }    
        }    
        //向任务队列添加任务    
        void PushTask(const T& in)
        {    
            //注意：新建线程还在判断中，这里需要使用互斥锁保证新建线程互斥
            Lock();    
            task_queue_.push(in);     
            Unlock();      
            WakeUp(); 
        }    
        //从任务队列获取任务  
        void PopTask(T& out)
        {    
            out = task_queue_.front();  
            out.Run();      
            task_queue_.pop();    
        }    
        ~ThreadPool()    
        {    
            pthread_mutex_destroy(&mtx_);    
            pthread_cond_destroy(&cond_);    
        }    
    };    
